/*********************************************************************************************************
* 模块名称：AT24Cxx.c
* 摘    要：AT24Cxx模块
* 当前版本：1.0.0
* 作    者：jadewo
* 完成日期：2025年05月22日
* 内    容：AT24Cxx
* 注    意：
**********************************************************************************************************
* 取代版本：
* 作    者：
* 完成日期：
* 修改内容：
* 修改文件：
*********************************************************************************************************/

/*********************************************************************************************************
*                                              包含头文件
*********************************************************************************************************/
#include "AT24Cxx.h"
#include "AT_I2C.h"
#include "gd32f30x_conf.h"
#include "Systick.h"

/*********************************************************************************************************
*                                              宏定义
*********************************************************************************************************/


/*********************************************************************************************************
*                                              枚举结构体
*********************************************************************************************************/

/*********************************************************************************************************
*                                              内部变量定义
*********************************************************************************************************/

/*********************************************************************************************************
*                                              内部函数声明
*********************************************************************************************************/
static unsigned char AT24CxxReadOneByte(unsigned short readAddr);                       //从指定地址读取一字节数据
static void AT24CxxWriteOneByte(unsigned short writeAddr, unsigned char dataToWrite);   //从指定地址写入一字节数据
/*********************************************************************************************************
*                                              内部函数实现
*********************************************************************************************************/
static unsigned char AT24CxxReadOneByte(unsigned short readAddr)
{ 
    unsigned char temp = 0; 

    GenI2CStartSig(); //发送起始信号 

    if(USER_DEFINE_EEPROM_TYPE > AT24C16) //如果内存字节大于 AT24C16(2047)
    {
        I2CSendByte(0XA0); //发送写命令
        I2CWaitAck(); //等待应答
        I2CSendByte(readAddr >> 8); //发送高地址
    }
    else //内存字节不大于 2047
    {

        I2CSendByte(0XA0 + ((readAddr / 256) << 1));//发送器件地址 0XA0，写数据 
    }

    I2CWaitAck(); //等待应答
    I2CSendByte(readAddr % 256); //发送 BYTE ADDRESS（字节的地址）
    I2CWaitAck(); //等待应答

    GenI2CStartSig(); //发送起始信号 
    I2CSendByte(0XA1); //发送 SLAVE ADDRESS，为了进入接收模式，1 0 1 0 x x x R/~W 
    I2CWaitAck(); //等待应答

    temp = I2CReadByte(0); //传入参数 0 表示发送非应答信号

    GenI2CStopSig(); //发送停止信号 

    return temp; //返回读取到的值
}

static void AT24CxxWriteOneByte(unsigned short writeAddr, unsigned char dataToWrite)
{ 
    GenI2CStartSig(); //发送起始信号

    if(USER_DEFINE_EEPROM_TYPE > AT24C16)
    {
        I2CSendByte(0XA0); //发送写命令
        I2CWaitAck();
        I2CSendByte(writeAddr >> 8); //发送高地址
    }
    else
    {
        //左移 1 位因为 LSB 是 R/~W,发送 SLAVE ADDRESS（字地址也包含其中） 
        I2CSendByte(0XA0 + ((writeAddr / 256) << 1)); 
    }

    I2CWaitAck(); //等待应答

    I2CSendByte(writeAddr % 256); //发送 BYTE ADDRESS（字节的地址）
    I2CWaitAck(); //等待应答

    I2CSendByte(dataToWrite); //发送待写入的字节 
    I2CWaitAck(); //等待应答

    GenI2CStopSig(); //发送停止信号 
    DelayNms(10); //在主器件产生停止信号后 SLAVE 开始内部数据的擦写,
    //在擦写过程中不在应答主器件的任何请求,数据手册上的 tWR 是 5ms 
}

/*********************************************************************************************************
*                                              API函数实现
*********************************************************************************************************/
void InitAT24Cxx(void)
{
    InitAT_I2C(); //初始化 AT_I2C 模块
}

unsigned char CheckAT24Cxx(void)
{
    unsigned char temp = 0;

    temp = AT24CxxReadOneByte(255); //避免每次开机都写 AT24Cxx 

    if(temp == 0X55) //检验是否 AT24Cxx 已写入
    {
        return 0; //检测成功
    }
    else //排除第一次初始化的情况
    {
        AT24CxxWriteOneByte(255, 0X55); //在地址 255 处写入字节 0X55

        temp = AT24CxxReadOneByte(255); //读取地址 255 的字节赋值给 temp

        if(temp == 0X55) //检测是否已经更改完成
        {
            return 0; //检测成功
        }
    }

    return 1; //以上条件不符合，检测失败 
}

void AT24CxxRead(unsigned short readAddr, unsigned char* pBuffer, unsigned short numToRead)
{
    while(numToRead) //数据未读完
    {
        *pBuffer = AT24CxxReadOneByte(readAddr); //逐字节读出存放到数据数组

        readAddr++; //读取字节地址加 1
        pBuffer++; //数据数组地址加 1
        numToRead--; //要读出的数据个数减 1
    }
}

void AT24CxxWrite(unsigned short writeAddr, unsigned char* pBuffer, unsigned short numToWrite)
{
    while(numToWrite) //数据未写完
    {
        AT24CxxWriteOneByte(writeAddr, *pBuffer); //逐字节写入数据数组

        writeAddr++; //写入字节地址加 1
        pBuffer++; //数据数组地址加 1
        numToWrite--; //要写入的数据个数减 1
    }
}

